/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.result

import android.app.Application
import android.content.Context
import com.example.result.dao.api.DaoApi
import com.example.result.dao.api.HttpLoggingInterceptor
import com.example.result.dao.db.DaoDb
import com.example.result.preference.Config
import com.lly.tboc.zhouyi.api.UploadFileApi
import com.lly.tboc.zhouyi.api.ZhouyiApi
import com.lly.tboc.zhouyi.db.GuaDao
import com.lly.tboc.zhouyi.db.YaoDao
import com.lly.tboc.zhouyi.db.ZhouyiDb
import dagger.Module
import dagger.Provides
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import javax.inject.Scope
import javax.inject.Singleton

/*
@Singleton
@Component(
    modules = [
        AndroidInjectionModule::class,
        AppModule::class,
        MainActivityModule::class]
)
interface AppComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: Application): Builder

        fun build(): AppComponent
    }

    fun inject(githubApp: ResultApp)
}
*/
@InstallIn(SingletonComponent::class)
@EntryPoint
interface ProviderEntryPoint {
    fun zhouyiDb(): ZhouyiDb
}

@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class IoDispatch

@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class MainDispatch

@Scope
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class DefaultDispatch

@Module
@InstallIn(SingletonComponent::class)
class AppModule {
    @Provides
    @Singleton
    fun provideDaoService(app: Application): DaoApi {
        return DaoApi.create(app)
    }

    @Provides
    @IoDispatch
    fun providerIoDispatch(): CoroutineDispatcher = Dispatchers.IO

    @Singleton
    @Provides
    fun provideDaoDb(app: Application): DaoDb {
        return DaoDb.create(app)
    }

    @Singleton
    @Provides
    fun provideGuaDao(zhouyiDb: ZhouyiDb): GuaDao {
        return zhouyiDb.guaDao()
    }

    @Singleton
    @Provides
    fun provideYaoDao(zhouyiDb: ZhouyiDb): YaoDao {
        return zhouyiDb.yaoDao()
    }

    @Singleton

    @Provides
    fun provideZhouyiService(app: Application): ZhouyiApi {
        return ZhouyiApi.create(Config.getUrl(app), HttpLoggingInterceptor())
    }

    @Singleton

    @Provides
    fun provideUploadFileService(app: Application): UploadFileApi {
        return UploadFileApi.create(Config.getUrl(app), HttpLoggingInterceptor())
    }

    @Singleton

    @Provides
    fun provideZhouyiDb(@ApplicationContext app: Context): ZhouyiDb {
        return ZhouyiDb.create(app)
    }
}

/*
@MustBeDocumented
@Target(
    AnnotationTarget.FUNCTION,
    AnnotationTarget.PROPERTY_GETTER,
    AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
*/

/*
@Suppress("unused")
@Module
abstract class ViewModelModule {
    @Binds
    @IntoMap
    @ViewModelKey(DaoViewModel::class)
    abstract fun bindDaoSectionViewModel(userViewModel: DaoViewModel): ViewModel

    @Binds
    @IntoMap
    @ViewModelKey(DaoContentModel::class)
    abstract fun bindDaoContentViewModel(userViewModel: DaoContentModel): ViewModel

    @Binds
    @IntoMap
    @ViewModelKey(GuaViewModel::class)
    abstract fun bindGuaViewModel(userViewModel: GuaViewModel): ViewModel

    @Binds
    @IntoMap
    @ViewModelKey(YaoViewModel::class)
    abstract fun bindYaoViewModel(userViewModel: YaoViewModel): ViewModel

    @Binds
    @IntoMap
    @ViewModelKey(ZhouyiSearchViewModel::class)
    abstract fun bindZhouyiSearchViewModel(userViewModel: ZhouyiSearchViewModel): ViewModel

    @Binds
    abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
}
*/

/*
@Singleton
class ViewModelFactory @Inject constructor(
    private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        val creator = creators[modelClass] ?: creators.entries.firstOrNull {
            modelClass.isAssignableFrom(it.key)
        }?.value ?: throw IllegalArgumentException("unknown model class $modelClass")
        @Suppress("UNCHECKED_CAST")
        return creator.get() as T
    }
}
*/

/*
@Suppress("unused")
@Module
abstract class MainActivityModule {
    @ContributesAndroidInjector(modules = [MainActivityFragmentBuildersModule::class])
    abstract fun contributeMainActivity(): MainActivity

    @ContributesAndroidInjector(modules = [ContainerActivityFragmentBuilderModule::class])
    abstract fun contributeContainerActivity(): ContainerActivity

    @ContributesAndroidInjector()
    abstract fun contributeMySuggestionProvider(): MySuggestionProvider
}
*/

/*
@Suppress("unused")
@Module
abstract class MainActivityFragmentBuildersModule {
    @ContributesAndroidInjector
    abstract fun contributeDaoFragment(): DaoFragment


    @ContributesAndroidInjector
    abstract fun contributeGuaFragment(): GuaFragment


}
*/

/*
@Suppress("unused")
@Module
abstract class ContainerActivityFragmentBuilderModule {
    @ContributesAndroidInjector
    abstract fun contributeDaoContentFragment(): DaoContentFragment

    @ContributesAndroidInjector
    abstract fun contributeYaoFragment(): YaoFragment

    @ContributesAndroidInjector
    abstract fun contributeSearchFragment(): SearchFragment
}
*/

